//
// Created by lvyer on 2021/12/2.
//

#include "common/ScreenFilter.h"

ScreenFilter::ScreenFilter() {

}

ScreenFilter::~ScreenFilter() {

}

//初始化着色器小程序 并编译着色器代码 并链接
void ScreenFilter::initFilter() {
    char vShaderStr[] =
            "#version 300 es                          \n"
            "layout(location = 0) in vec4 vPosition;  \n"
            "layout(location = 1) in vec2 vCoordinate;  \n"
            "out vec2 aCoordinate;                       \n"
            "void main()                              \n"
            "{                                        \n"
            "   gl_Position = vPosition;              \n"
            "   aCoordinate = vCoordinate;              \n"
            "}                                        \n";

    char fShaderStr[] =
            "#version 300 es                              \n"
            "precision mediump float;                     \n"
            "uniform sampler2D fTexture;                   \n"
            "in vec2 aCoordinate;                     \n"
            "out vec4 fragColor;                          \n"
            "void main()                                  \n"
            "{                                            \n"
            "   fragColor = texture(fTexture, aCoordinate);  \n"
            "}                                            \n";
    m_ProgramObj = GLTools::createProgram(vShaderStr, fShaderStr, m_VertexShader, m_FragmentShader);

    // 通过id通知GPU 我们要使用这个着色器程序了
    glUseProgram(m_ProgramObj);
    GLfloat vertices[] = {
            //坐标 ..  纹理坐标
            -1.0f, -1.0f, 0.0f, 0.0f,
            1.0f, -1.0f, 1.0f, 0.0f,
            -1.0f, 1.0f, 0.0f, 1.0f,
            1.0f, 1.0f, 1.0f, 1.0f
    };
    unsigned int indices[] = {
            0, 1, 2, // first triangle
            1, 2, 3  // second triangle
    };
    //初始化创建 VBO  VAO  EBO 对象
    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);
    glGenBuffers(1, &EBO);

    //为当前使用的着色器程序绑定VAO 顶点缓冲数组对象
    glBindVertexArray(VAO);

    //为当前绑定 顶点缓冲对象
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    //为当前已绑定的缓冲对象填充数据
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

    // 为顶点着色器的 0号变量赋值
    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void *) 0);
    glEnableVertexAttribArray(0);
    // 为顶点着色器的 1号变量赋值  数量4个，每一个长度为 2个顶点+2个纹理坐标的float长度 第一次取值从跳过2个float长度
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float),
                          (void *) (2 * sizeof(float)));
    glEnableVertexAttribArray(1);

    // 片元着色器：采样器
    fTexture = glGetUniformLocation(m_ProgramObj, "fTexture");
}

void ScreenFilter::changerFilter(int width, int height) {
    this->width = width;
    this->height = height;
    glViewport(0, 0, width, height);
}

int ScreenFilter::drawFilter(int textureId) {
    if (m_ProgramObj == 0)
        return -1;
    //清除上次渲染内容
    glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glClearColor(0.0, 0.0, 1.0, 1.0);

    glUseProgram(m_ProgramObj);
    glBindVertexArray(VAO);

    //片元 fTexture
    // 激活图层
    if (textureId != -1) {
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, textureId);
    }
    // 传递采样器
    glUniform1i(fTexture, 0);
    // 通知 opengl 绘制
    //正式将纹理和数据渲染到FBO中，最终会绘制到与之绑定的纹理id中
//    glDrawArrays(GL_TRIANGLES, 0, 4);
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
    //解绑操作
    glBindVertexArray(0);
    glBindTexture(GL_TEXTURE_2D, 0);

    //返回与FBO绑定的纹理id  颜色附着点
    return m_FboTextureId;
}
